#include "DRR_Scheduler.h"

/* This function implements the logic of DRR Scheduler,
	According to DRR each Flow get credit on it's turn (crdit = quantum*weight),
	according to this credit the scheduler let each flow send specific amount of packets.

	steps:
	1. give the current flow credit.
	2. while there is a packet and enough credit for the next packet:
	2.1. reduce the credit according to packet length
	2.2. Take out first packet from current flow's head packets queue
	2.2. Write to the output file the result
	2.3. Advance the current_time (to the time after this packet was sent).
	2.4. Load from input file all the new packets that arrived to the system
	until that time (if not reached to the end of file yet).

	On success this function return 0, and on fail return 1.
*/
int DRR_Scheduler::ScheduleCurrentFlow()
{
	current_flow->AddCredit(quantum);
	while (current_flow->Get1PacketLength() && // while the queue is not empty and the credit is more than first packet length
			(current_flow->GetCredit() >= current_flow->Get1PacketLength()) ) 
	{	
		current_flow->ReduceCredit();
		long int return_time = current_flow->Remove_Pkt_From_Flow(current_time, outfile_p);
		if (return_time == -1)
		{
			cerr << "Failed to remove packet from flow.\n";
			return 1;
		}
		else
		{
			current_time = return_time;
			if (!end_of_input)
			{
				if (Load_data_to_Schedule())
				{
					cerr << "Failed to Load data from file.\n";
					return 1;
				}
			}

		}
		
	}
	return 0;
}

/*
* this function override Scheduler HandleAllEmpty
* the function adds special treatment for the credit and then calls its parent implementation.
*/
int DRR_Scheduler::HandleAllEmpty()
{
	EmptyAllCredit();
	return Scheduler::HandleAllEmpty();
}

/*
* this function override Scheduler HandleCurrentFlowEmpty
* the function zerorize credit for current flow and the calls its parent implementation
*/
void DRR_Scheduler::HandleCurrentFlowEmpty()
{
	EmptyCurrentCredit();
	Scheduler::HandleCurrentFlowEmpty();
}

/*
* this function zerorize all flows credit, 
* the function should be called when all flows are empty
*/
void DRR_Scheduler::EmptyAllCredit()
{
	Flow* tmp_flow = head_flow_queue;
	while (tmp_flow != NULL)
	{
		tmp_flow->ZerorizeCredit();
		tmp_flow = tmp_flow->next_flow;
	}
}

/*
* this function zerorize current flow credit,
* the function should be called when current flow is empty 
* but have credit from previous scheduling.
*/
void DRR_Scheduler::EmptyCurrentCredit()
{
	current_flow->ZerorizeCredit();
}